package com.geely.club.util.openapiclient;

/**
 * Created by mengyangyang on 2015-10-15.
 */

import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import cn.evun.gap.openapi.client.binding.RopClientException;
import cn.evun.gap.openapi.client.binding.ServiceMethodDefinition;
import cn.evun.gap.openapi.client.binding.ServiceRegistry;
import cn.evun.gap.openapi.client.model.openapi.ServiceMethodParam;
import cn.evun.gap.openapi.client.utils.StringUtils;

public class ServiceProxy implements InvocationHandler, Serializable {

    private static final long serialVersionUID = 1L;

    private ServiceRegistry serviceRegistry;

    private OpenApiClient client;

    public ServiceProxy(ServiceRegistry serviceRegistry, OpenApiClient client) {
        this.serviceRegistry = serviceRegistry;
        this.client = client;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args)
            throws Throwable {

        if (null == args || args.length == 0) {
            throw new RopClientException("service method args forbid null, must have param serviceMethodParam!");
        }

        Object obj = args[args.length - 1];

        if (!(obj instanceof ServiceMethodParam)) {
            throw new RopClientException("service method last args must be serviceMethodParam!");
        }

        ServiceMethodParam serviceMethodParam = (ServiceMethodParam) obj;

        ServiceMethodDefinition serviceMethodDefinition = serviceRegistry.getServiceMethodDefinition(method);

        if (null == serviceMethodDefinition) {
            serviceMethodDefinition = serviceRegistry.addServiceMethodDefinition(method, serviceMethodParam);
        } else {
            buildNewServiceMethodDefinition(serviceMethodDefinition, serviceMethodParam);
        }
        //调用的方法发送请求
        return client.service(method, serviceMethodDefinition, args);
    }

    public static void buildNewServiceMethodDefinition(ServiceMethodDefinition serviceMethodDefinition, ServiceMethodParam serviceMethodParam) {
        serviceMethodDefinition.setVersion(serviceMethodParam.getV());
        serviceMethodDefinition.setAction(serviceMethodParam.getAction());
        serviceMethodDefinition.setTicket(serviceMethodParam.getTicket());
        if (StringUtils.isEmpty(serviceMethodDefinition.getVersion())) {
            serviceMethodDefinition.setVersion(serviceMethodDefinition.getOldVersion());
        }
        if (null == serviceMethodDefinition.getAction()) {
            serviceMethodDefinition.setAction(serviceMethodDefinition.getOldAction());
        }
    }

    @SuppressWarnings("unchecked")
    public static <T> T newMapperProxy(Class<T> serviceInterface, ServiceRegistry serviceRegistry, OpenApiClient openApiClient) {
        ClassLoader classLoader = serviceInterface.getClassLoader();
        Class<?>[] interfaces = new Class[]{serviceInterface};
        ServiceProxy proxy = new ServiceProxy(serviceRegistry, openApiClient);
        return (T) Proxy.newProxyInstance(classLoader, interfaces, proxy);
    }
}
